package com.xpc.rpc.codec;

import com.xpc.rpc.common.enums.RpcMsgType;
import com.xpc.rpc.common.enums.SerializationType;
import com.xpc.rpc.common.serialization.Serialization;
import com.xpc.rpc.protocol.ProtocolMessage;
import com.xpc.rpc.protocol.header.RpcHeader;
import com.xpc.rpc.protocol.request.RpcRequest;
import com.xpc.rpc.protocol.response.RpcResponse;
import com.xpc.rpc.serialization.jdk.JdkSerialization;
import com.xpc.rpc.spi.loader.ExtensionLoader;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.ByteToMessageDecoder;

import java.util.List;

/**
 * 解码器
 */
public class RpcDecoder extends ByteToMessageDecoder implements RpcCoder {


    @Override
    protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception {
        if(in.readableBytes() < 20) {
            return;
        }
        //拿到请求消息类型
        int msgType = in.readInt();

        //拿到请求体长度
        int bodyLen = in.readInt();

        //拿到请求id
        long requestId = in.readLong();

        //拿到序列化类型
        int serializationType = in.readInt();

        if(in.readableBytes() < bodyLen) {
            //表示读取的数据还不够
            in.resetReaderIndex();
            return;
        }

        //获取请求体
        byte[] data = new byte[bodyLen];
        in.readBytes(data);

        RpcHeader rpcHeader = new RpcHeader();
        rpcHeader.setRequestId(requestId);
        rpcHeader.setBodyLen(bodyLen);
        rpcHeader.setMsgType(msgType);
        rpcHeader.setSerializationType(serializationType);

        String serializationValue = SerializationType.getVal(serializationType);
        //获取序列化接口
        Serialization serialization = ExtensionLoader.getExtension(Serialization.class, serializationValue);

        ProtocolMessage protocolMessage = new ProtocolMessage();
        protocolMessage.setRpcHeader(rpcHeader);


        RpcMsgType rpcMsgType = RpcMsgType.findByType(msgType);
        switch (rpcMsgType){
            case REQUEST:
                RpcRequest request = serialization.deserialize(data, RpcRequest.class);
                protocolMessage.setT(request);
                break;
            case RESPONSE:
                RpcResponse response = serialization.deserialize(data, RpcResponse.class);
                protocolMessage.setT(response);
                break;
        }

        //更新读索引
        in.markReaderIndex();

        //最后通过管道写出去
        out.add(protocolMessage);
    }

}
